package com.duke.shaking.net;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.json.JSONObject;


import com.duke.shaking.pojo.Message;
import com.duke.shaking.storage.DataManager;

import android.content.Context;
import android.os.Handler;

public class MessageSender {
	public interface MessageSendListener {
		public void onMessageSent(Message msg, boolean success);
	}
	
	private static String TAG = "messageSender";
	private static MessageSender shared;
	
	private Context context;
	private List<MessageSendListener> listeners;
	private SendThread sendThread;
	private Handler handler;
	
	private BlockingQueue<Message> msgQueue;
	
	public static MessageSender getShared() {
		return shared;
	}
	
	public static void createShared(Context context) {
		if (shared == null) {
			shared = new MessageSender(context);
		}
	}
	
	public MessageSender(Context context) {
		this.context = context;
		msgQueue = new LinkedBlockingQueue<Message>();
		listeners = new ArrayList<MessageSendListener>();
		handler = new Handler();
	}
	
	public void addListener(MessageSendListener listener) {
		listeners.add(listener);
	}
	
	public void removeListener(MessageSendListener listener) {
		listeners.remove(listener);
	}
	
	public void sendMsg(Message msg) {
		try {
			msgQueue.put(msg);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void start() {
		if (sendThread == null) {
			sendThread = new SendThread();
			sendThread.start();
		}
	}
	
	public void stop() {
		if (sendThread != null) {
			sendThread.setStop();
			sendThread = null;
		}
	}
	
	private class ResultRunnable implements Runnable {

		private boolean result;
		private Message msg;
		public ResultRunnable(Message msg, boolean result) {
			this.msg = msg;
			this.result = result;
		}
		
		public void run() {
			for (MessageSendListener l : listeners) {
				l.onMessageSent(msg, result);
			}
		}
		
	}
	
	public void afterSend(Message msg, boolean success) {
		int state = 0;
		if (success) {
			state = Message.SEND_STATE_SUCCESS;
		}
		else {
			state = Message.SEND_STATE_FAILED;
		}
		
		msg.setSendState(state);
		DataManager.getShared().setMessageSendStateById(
				msg.getMsgId(), 
				state);

		handler.post(new ResultRunnable(msg, success));
	}
	
	private void processSendResult(String jsonStr, Message msg) {
		if (jsonStr == null) {
			afterSend(msg, false);
			return;
		}
		jsonStr = jsonStr.trim();
		if (jsonStr.equals("")) {
			afterSend(msg, false);
			return;
		}
		JSONObject jsonObj;
		try {
			jsonObj = new JSONObject(jsonStr);
			JSONObject headerJson = jsonObj.optJSONObject(NetUtils.HEADER);
			if (headerJson == null) {
				afterSend(msg, false);
				return;
			}
			int result = headerJson.optInt("result", 0);
			if (result != 1) {
				afterSend(msg, false);
			}
			else {
				afterSend(msg, true);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			afterSend(msg, false);
		}
	}
	
	private class SendThread extends Thread {
		
		private boolean stoped;
		public SendThread() {
			stoped = false;
		}
		
		@Override 
        public void run() {
			try {
				Message msg;
				while(!stoped) {
					if ((msg = msgQueue.poll(200, TimeUnit.MILLISECONDS)) != null) {
						String resp = NetUtils.sendMessage(context,  
							msg);
						processSendResult(resp, msg);
					}
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		public void setStop() {
			stoped = true;
		}
		
	}
}
